package com.ifd.gui.as400;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

import org.apache.log4j.Logger;

import com.ibm.as400.access.AS400;
import com.ibm.as400.access.AS400Bin4;
import com.ibm.as400.access.AS400Message;
import com.ibm.as400.access.AS400Text;
import com.ibm.as400.access.ProgramCall;
import com.ibm.as400.access.ProgramParameter;
import com.ibm.as400.access.SpooledFile;
import com.ifd.as400.IFDConnectionPool;
import com.ifd.as400.IFDException;

public class VSpooledFileList implements ActionListener{
	
	static final Logger logger = Logger.getLogger(VSpooledFileList.class);
	
	// Spooled File List Filter
	private String ftQualOutQ = "*ALL                ";
	private String ftSpUser = "*CURRENT", ftSpFormType = "*ALL",
			ftSpUserData = "*ALL", ftSpName;
	private String ftJobName = null, ftJobUser = null, ftJobNum = null;

	private ProgramCall pgm;
	private Vector<Object> data;
	private Vector<Object> columns;
	private JTable table;
	private SpooledFile selectedSplf=null;
	
	private JDialog dialog;
	public VSpooledFileList() {
		super();
	}

	public SpooledFile getSelectedSpooledFile() throws IFDException{
		load();
		dialog = new JDialog();
		dialog.setSize(900, 600);
		dialog.setModal(true);
		dialog.setLayout(new BorderLayout());
		JScrollPane pane=new JScrollPane(cloneDataTable());
		dialog.getContentPane().add(pane,BorderLayout.CENTER);
		dialog.getContentPane().add(buildButtonsPanel(dialog.getWidth()),BorderLayout.SOUTH);
		dialog.setTitle("List of Spooled Files");
		dialog.setLocationRelativeTo(null);
		dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
		dialog.setVisible(true);
		return selectedSplf;
	}
	
	private Component buildButtonsPanel(int width) {
		JPanel panel = new JPanel(null);
		panel.setPreferredSize(new Dimension(width, 50));
		int offset = width/11;
		JButton button=new JButton();
		button.setText("Select");
		button.setMnemonic(KeyEvent.VK_S);
		button.addActionListener(this);
		button.setActionCommand("select");
		button.setBounds(offset*4, 5, offset, 25);
		panel.add(button);
		
		button=new JButton();
		button.setText("Cancel");
		button.setMnemonic(KeyEvent.VK_C);
		button.addActionListener(this);
		button.setActionCommand("cancel");
		button.setBounds(offset*6, 5, offset, 25);
		panel.add(button);
		
		return panel;
	}
	
	public JTable getDataTable(){
		return table;
	}
	
	/**
	 * Call this method after @link load() to retrieve the JTable with Spooled
	 * Files list
	 * 
	 * @return
	 */
	public JTable cloneDataTable() {
		columns = new Vector<Object>();
		columns.addElement("File Name");
		columns.addElement("File Number");
		columns.addElement("User");
		columns.addElement("Device/Queue");
		columns.addElement("User Data");
		columns.addElement("Form Type");
		columns.addElement("Status");
		columns.addElement("Total Pages");
		columns.addElement("Copies");
		columns.addElement("Job Name");
		columns.addElement("Job Number");
		table = new JTable(data, columns) {
			public boolean isCellEditable(int rowIndex, int vColIndex) {
				return false;
			}
		
			public Component prepareRenderer(TableCellRenderer renderer,
					int index_row, int index_col) {
				Component comp = super.prepareRenderer(renderer, index_row,
						index_col);
				// odd col index, selected or not selected
				if (index_row % 2 != 0) {
					comp.setBackground(new Color(243,243,243));
				} else {
					comp.setBackground(Color.white);
				}
				if(isRowSelected(index_row))	//highlight the selected row
				{
					comp.setBackground(Color.GRAY);
					comp.setForeground(Color.WHITE);
				}else{
					comp.setForeground(Color.BLACK);
				}
				return comp;
			}
			
			
		};
		table.getColumnModel().getColumn(0).setPreferredWidth(75);
		table.getColumnModel().getColumn(1).setPreferredWidth(75);
		table.getColumnModel().getColumn(2).setPreferredWidth(75);
		table.getColumnModel().getColumn(3).setPreferredWidth(90);
		table.getColumnModel().getColumn(4).setPreferredWidth(80);
		table.getColumnModel().getColumn(5).setPreferredWidth(80);
		table.getColumnModel().getColumn(6).setPreferredWidth(80);
		table.getColumnModel().getColumn(7).setPreferredWidth(80);
		table.getColumnModel().getColumn(8).setPreferredWidth(80);
		table.getColumnModel().getColumn(9).setPreferredWidth(80);
		table.getColumnModel().getColumn(10).setPreferredWidth(80);
		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		table.getColumnModel().setColumnSelectionAllowed(false);
		table.getTableHeader().setReorderingAllowed(false);
		table.getColumnModel().setColumnSelectionAllowed(false);
		table.getTableHeader().setBackground(Color.DARK_GRAY);
		table.setRowSelectionAllowed(true);
		return table;
	}

	public void addColumn(TableColumnModel colModel, int size, String header) {
		int index = colModel.getColumnCount();
		TableColumn column = new TableColumn(index, size);
		column.setHeaderValue(header);
	}

	public void load() throws IFDException {
		pgm = new ProgramCall(IFDConnectionPool.getAS400());
		createUserSpace();
		buildSpoolList();
	}

	public void setQueueFilter(String outq, String oqlb) {
		if (!outq.trim().equalsIgnoreCase("*ALL")) {
			if (oqlb.trim().length() <= 0)
				oqlb = "*LIBL";
			ftQualOutQ = outq.trim();
			if (outq.length() < 10)
				ftQualOutQ = ftQualOutQ
						+ "          ".substring(0, 10 - outq.length());
			ftQualOutQ = ftQualOutQ.concat(oqlb);
		}
	}

	public void setUserFilter(String user) {
		ftSpUser = user;
	}

	public void setFormTypeFilter(String formtype) {
		ftSpFormType = formtype;
	}

	public void setUserDataFilter(String userdata) {
		ftSpUserData = userdata;
	}

	public void setSpoolNameFilter(String name) {
		ftSpName = name;
	}

	public void setJobFilter(String jobName, String jobUser, String jobNum) {
		ftJobName = jobName;
		ftJobUser = jobUser;
		ftJobNum = jobNum;
	}

	private void createUserSpace() throws IFDException {
		ProgramParameter parms[] = new ProgramParameter[8];
		AS400 as400 = IFDConnectionPool.getAS400();
		byte[] nil = new byte[1];
		nil[0] = 0x00;

		parms[0] = new ProgramParameter( // User space name
				(new AS400Text(20, as400)).toBytes("TMPSPACE  QTEMP     "));
		parms[1] = new ProgramParameter( // Extended Attribute
				(new AS400Text(10, as400)).toBytes(""));
		parms[2] = new ProgramParameter( // User space length
				(new AS400Bin4().toBytes(1000)));
		parms[3] = new ProgramParameter( // Initial value
				(new AS400Text(1, as400)).toBytes(new String(nil)));
		parms[4] = new ProgramParameter( // Public authority
				(new AS400Text(10, as400)).toBytes("*ALL"));
		parms[5] = new ProgramParameter( // Text description
				(new AS400Text(50, as400)).toBytes("Spooled File List"));
		parms[6] = new ProgramParameter( // Replace
				(new AS400Text(10, as400)).toBytes("*YES"));
		parms[7] = new ProgramParameter(100); // Error code
		try {
			if (!pgm.run("/QSYS.LIB/%LIBL%.LIB/QUSCRTUS.PGM", parms)) {
				AS400Message[] msgs = pgm.getMessageList();
				for (AS400Message msg : msgs) {
					logger.error(msg.getText());
				}
				throw new IFDException(msgs[0].getText(), logger);
			}
		} catch (Exception e) {
			throw new IFDException(e.getLocalizedMessage(), logger, e);
		}
	}

	private void buildSpoolList() throws IFDException {
		AS400 as400 = IFDConnectionPool.getAS400();

		AS400Bin4 bin4 = new AS400Bin4();
		ProgramParameter parms[] = new ProgramParameter[7];
		parms[0] = new ProgramParameter( // User space name
				(new AS400Text(20, as400)).toBytes("TMPSPACE  QTEMP     "));
		parms[1] = new ProgramParameter( // Format name
				(new AS400Text(8, as400)).toBytes("SPLF0300"));
		parms[2] = new ProgramParameter( // User name
				(new AS400Text(10, as400).toBytes(ftSpUser)));
		parms[3] = new ProgramParameter( // Qualified output queue name
				(new AS400Text(20, as400)).toBytes(ftQualOutQ));
		parms[4] = new ProgramParameter( // Form type
				(new AS400Text(10, as400)).toBytes(ftSpFormType));
		parms[5] = new ProgramParameter( // User-specified data
				(new AS400Text(10, as400)).toBytes(ftSpUserData));
		parms[6] = new ProgramParameter(100);// Error code
		try {
			if (!pgm.run("/QSYS.LIB/%LIBL%.LIB/QUSLSPL.PGM", parms)) {
				AS400Message[] msgs = pgm.getMessageList();
				for (AS400Message msg : msgs) {
					logger.error(msg.getText());
				}
				throw new IFDException(msgs[0].getText(), logger);
			}
		} catch (Exception e) {
			throw new IFDException(e.getLocalizedMessage(), logger, e);
		}

		AS400Text txt10 = new AS400Text(10, IFDConnectionPool.getAS400());
		AS400Text txt6 = new AS400Text(6, IFDConnectionPool.getAS400());

		int offListStart = bin4.toInt(retrieveTMPSPACE(125, 4)) + 1;
		int nbrEntries = bin4.toInt(retrieveTMPSPACE(133, 4));
		int entrySize = bin4.toInt(retrieveTMPSPACE(137, 4));
		data = new Vector(nbrEntries);
		for (int i = 0; i < nbrEntries; i++) {
			byte[] entryData = retrieveTMPSPACE(offListStart, entrySize);
			String jobName = txt10.toObject(entryData, 0).toString();
			String jobUser = txt10.toObject(entryData, 10).toString();
			String jobNumber = txt6.toObject(entryData, 20).toString();
			String spName = txt10.toObject(entryData, 26).toString();
			if (validJobFilter(jobName, jobUser, jobNumber, spName)) {
				Vector<Object> rec = new Vector<Object>();
				rec.add(spName); // Spool file name
				rec.add(bin4.toInt(entryData, 36)); // Spool file number
				rec.add(jobUser); // Spool file user
				rec.add(txt10.toObject(entryData, 88).toString()); // Outqueue
																	// name
				rec.add(txt10.toObject(entryData, 68).toString()); // User data
				rec.add(txt10.toObject(entryData, 78).toString()); // Form type
				rec.add(retrieveStatus(bin4.toInt(entryData, 40))); // Spool
																	// file
																	// status
				rec.add(bin4.toInt(entryData, 120)); // Total pages
				rec.add(bin4.toInt(entryData, 124)); // Copies
				rec.add(jobName); // Job name
				rec.add(jobNumber); // Job number
				data.addElement(rec);
			}
			offListStart = offListStart + entrySize;
		}
	}

	private boolean validJobFilter(String jobName, String jobUser,
			String jobNumber, String spName) {

		if (ftJobName != null && !ftJobName.equalsIgnoreCase(jobName))
			return false;
		if (ftJobUser != null) {
			if (ftJobUser.equalsIgnoreCase("*CURRENT"))
				ftJobUser = IFDConnectionPool.getAS400().getUserId();
			if (!ftJobUser.equalsIgnoreCase(jobUser))
				return false;
		}
		if (ftJobNum != null && !ftJobNum.equalsIgnoreCase(jobNumber))
			return false;
		if (ftSpName != null && !ftSpName.equalsIgnoreCase("*ALL")
				&& !ftSpName.equalsIgnoreCase(spName))
			return false;
		return true;
	}

	private String retrieveStatus(int status) {
		switch (status) {
		case 1:
			return "RDY";
		case 2:
			return "OPN";
		case 3:
			return "CLO";
		case 4:
			return "SAV";
		case 5:
			return "WTR";
		case 6:
			return "HLD";
		case 7:
			return "MSGW ";
		case 8:
			return "PND";
		case 9:
			return "PRT";
		case 10:
			return "FIN";
		case 11:
			return "SND";
		case 12:
			return "DFR";
		}
		return "";
	}

	private byte[] retrieveTMPSPACE(int start, int len) throws IFDException {
		ProgramParameter parms[] = new ProgramParameter[5];
		AS400 as400 = IFDConnectionPool.getAS400();
		parms[0] = new ProgramParameter( // User space name
				(new AS400Text(20, as400)).toBytes("TMPSPACE  QTEMP     "));
		parms[1] = new ProgramParameter( // Start position
				(new AS400Bin4()).toBytes(start));
		parms[2] = new ProgramParameter( // Length of data
				(new AS400Bin4().toBytes(len)));
		parms[3] = new ProgramParameter(len);// Buffer length
		parms[4] = new ProgramParameter(100); // Error code

		try {
			if (!pgm.run("/QSYS.LIB/%LIBL%.LIB/QUSRTVUS.PGM", parms)) {
				AS400Message[] msgs = pgm.getMessageList();
				for (AS400Message msg : msgs) {
					logger.error(msg.getText());
				}
				throw new IFDException(msgs[0].getText(), logger);
			}
		} catch (Exception e) {
			throw new IFDException(e.getLocalizedMessage(), logger, e);
		}

		return parms[3].getOutputData();
	}

	public void actionPerformed(ActionEvent e) {
		String cmd = e.getActionCommand();
		selectedSplf=null;
		if(cmd.equalsIgnoreCase("select")){
			int row = getDataTable().getSelectedRow();
			if(row<data.size()){
				Vector<Object> rec = (Vector<Object>) data.elementAt(row);
				String spName=(String)rec.elementAt(0);
				int spNum=((Integer)rec.elementAt(1)).intValue();
				String jobName = (String)rec.elementAt(9);
				String jobUser = (String)rec.elementAt(2);
				String jobNum = (String)rec.elementAt(10);
				selectedSplf=new SpooledFile(IFDConnectionPool.getAS400(), 
						spName, spNum, jobName, jobUser, jobNum);
			}
			dialog.dispose();
		}else if(cmd.equalsIgnoreCase("cancel")){
			dialog.dispose();
		}
	}

}
